//
// Created by Administrator on 2021/9/24.
//
#ifndef HELLOOPENGL_SHADER_H
#define HELLOOPENGL_SHADER_H
#include <vector>
#include <cassert>

#include "../constant/Properties.h"
#include "../util/Log.h"
#include "../util/FileUtil.h"
#include "../math/Matrix4x4.h"

/**
 * 类型
 */
enum ShaderAttribType{
    //顶点坐标
    VERTEX,
    //顶点坐标索引
    INDICES,
    //顶点颜色
    COLOR,
    //顶点UV
    UV,
    //顶点法线
    NORMAL,
    //其他，留备用
    ORTHER
};

/**
 * 模式
 * #define GL_POINTS 0x0000
 * #define GL_LINES 0x0001
 * #define GL_LINE_LOOP 0x0002
 * #define GL_LINE_STRIP 0x0003
 * #define GL_TRIANGLES 0x0004
 * #define GL_TRIANGLE_STRIP 0x0005
 * #define GL_TRIANGLE_FAN 0x0006
 */
enum DrawMode {
    M_POINTS = GL_POINTS,
    M_LINES = GL_LINES,
    M_LINE_LOOP = GL_LINE_LOOP,
    M_LINE_STRIP = GL_LINE_STRIP,
    M_TRIANGLES = GL_TRIANGLES,
    M_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
    M_TRIANGLE_FAN = GL_TRIANGLE_FAN
};

/**
 * attribute 操作对象，创建VBO使用
 * //1、 VBO unsign int对象
 * //2、 attribute的index
 * //3、 attribute的numPoints
 * //4、 attribute的类型
 * //5、 attribute值是否normalize
 */
class ShaderAttribSetter{
public:
    bool setVBOFlag = false;
    //类型
    ShaderAttribType type;
    //VBO
    unsigned int VBO = 0;
    //shader中该字段的下标
    int index = 0;
    //参数个数，如 vec3-> 3, vec4->4
    int numPoints = 1;
    //类型，0:GL_FLOAT 1:GL_UNSIGNED_INT 2:GL_UNSIGNED_BYTE TODO 这里后面考虑优化
    int glType = 0;
    bool normalize = false;
};

class Shader {
private:

    //编译后shader程序
    unsigned int program;
    //是否有下标，对应drawElements()还是drawArrays()
    bool indicesFlag = false;
    //顶点数量
    int drawCt = 0;
    /**
     * 编译Shder源码
     * @param vertexShaderSource  vs
     * @param fragmentShaderSource fs
     */
    void initProgram(const char* vertexShaderSource, const char* fragmentShaderSource);
    /**
     * 类型转换
     * @param type
     * @return
     */
    unsigned int switchGlType(int type);

public:
    std::vector<ShaderAttribSetter> shaderAttribSetter;
    /**
     * 获得shder对象，使用默认shder
     */
    Shader();
    /**
     * 获得shader对象并编译
     * @param vsFilePath
     * @param fsFilePath
     */
    Shader(const char* vsFilePath, const char* fsFilePath);
    /**
     * 初始化shader的所有attribute
     */
    void initAttributeArrays();
    void initAttribVBOArray(ShaderAttribType type, std::vector<float> attriArray);
    void setAttribPointer();
    void setUniform(const char* uniformVar, const Matrix4x4& m) const;
    void draw(GLuint drawModel);
};

#endif //HELLOOPENGL_SHADER_H
